확장성 높은 코드의 재구성, 리팩토링 CSharp :: C#일반[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

C#일반
[1]
등록일:2008-03-27 20:52:13 (0%)
작성자:갤러리정
제목:확장성 높은 코드의 재구성, 리팩토링 CSharp
[C#] 확장성 높은 코드의 재구성, 리팩토링
 
[ 서우석(카이스트 대학원) 2005/10/10]
 
개발자는 자신이 작성한 코드를 끊임없이 변경하고 수정하며 최적화한다. 이는 보다 나은 코드를 작성하기 위한 과정으로 함수와 변수의 이름을 변경하거나, 매우 길게 늘어져 있는 코드를 별도의 함수로 분리하거나, 또는 매개 변수의 수를 추가 또는 제거하기도 한다.

리팩토링(Refactoring)은 이와 같이 개발자가 기존의 코드를 변경하는 일련의 작업을 지칭하는 것으로써, 코드의 성능을 개선하기 보다는 코드의 구조를 개선하여 관리하기 쉬우며 확장성이 높은 코드를 만들어 내는 프로세스이다.

그 러나 리팩토링이 특정한 목표를 달성하기 위해서 만들어진 새롭게 만들어진 이론이라고 볼 수는 없다. 단지 개발자들이 그 동안 해왔던 활동에 이름을 부여하여 보다 명시적으로 만들었을 뿐이다(리팩토링이 절대로 개발자에게 있어서 또 다른 작업이 되어서는 안 된다).

리팩토링에서 제안하는 지침의 수는 70여 가지에 이르며, 몇몇 리팩토링들은 매우 간단하고 분명해서 다른 리팩토링 기법에 활용되기도 한다. 예를 들어, "매직 넘버를 기호 상수로 대체하라."라는 지침은 코드를 작성할 때 특정한 값을 코드에 입력하지 말고 이름 상수를 만들라는 의미이다. 다음 <소스 1>에서 10이 무엇을 의미하는가?

class PageManager{  
public static int totalArticle (int nTotalPage)
  {
    return 10 * nTotalPage;
  }
}
소스 1 - 리팩토링을 적용하기 전의 코드

함수의 이름으로 추측컨데, 아마도 10은 한 페이지에 출력되는 글의 수일 것이다. 이 코드는 "매직 넘버를 기호 상수로 대체하라."라는 지침을 적용하여 다음과 같이 리팩토링할 수 있다.

Class PageManager{
  public const int ARTICLES_PER_PAGE = 10;
  public static int totalArticle (int nTotalPage)
  {
    return ARTICLES_PER_PAGE * nTotalPage;
  }
}
소스 2 - 리팩토링을 적용한 후의 코드

<소스 2>의 리팩토링된 코드는 두 가지 측면에서 개선되었는데, 우선 코드의 가독성이 높아졌고 한 페이지에 출력되는 글의 수를 변경하고자 할 때 모든 10을 변경하지 않고 이름 상수만 변경할 수 있다.

하지만 모든 리팩토링이 앞의 예와 같이 단순하지 않을 뿐만 아니라, 어떤 리팩토링들은 리팩토링을 수행하기 위해서 보다 작은 규모의 리팩토링들을 병행해야 하기도 한다.

Visual Studio Team System(VSTS)에서의 리팩토링
만 약 개발자가 리팩토링을 툴의 도움 없이 적용한다면 아마도 많은 시간을 투자해야 할 것이다. 물론 점차적으로 완성도가 높아지는 코드를 보면서 스스로 만족해할 수는 있겠지만, 툴을 제대로 활용하지 않는다면, 코드를 복사하고 붙여 넣고, 찾아서 대체하고, 컴파일하고 테스트하는 반복적인 작업에 리팩토링이 부담스럽게 느껴지게 될 것이다. 또한 리팩토링을 수행하는 도중에 코드가 다르게 작동하거나 오류가 포함된 코드가 작성될 수 있다.

하지만 VSTS에서는 이 모든 작업이 매우 간단하고 편리하다. 리팩토링하고자 하는 코드를 선택하고 마우스 오른쪽 버튼을 클릭하여 Refactor 메뉴에서 원하는 기법을 선택한다. VSTS에서 지원하는 리팩토링 기능은 다음 <표 1>과 같다.

<표 1> Visual Studio 2005가 지원하는 리팩토링 기법  

리팩토링 기법 의미
Extract Method 선택한 코드를 새로운 메서드로 정의한다.
Encapsulate Field public 필드를 private 필드로 바꾸고 기존의 필드는 property를 사용하여 캡슐화한다.
Extract Interface 기존의 타입 멤버를 기반으로 새로운 인터페이스 타입을 정의한다.
Reorder Parameters 매개 변수를 재정렬한다.
Remove Parameters 매개 변수를 제거한다.
Rename 메서드 이름이나 필드, 지역 변수 등의 이름을 일괄적으로 변경한다.
Promote Local Variable to Parameter 지역 변수를 매개 변수로 이동시킨다.



그 리고 VSTS가 제공하는 리팩토링 기법들은 언제나 미리보기(Preview) 기능을 제공하기 때문에, 코드가 변경되고 난 후의 모습도 미리 확인할 수 있다. 이 글에서는 <표 1>에서 소개한 리팩토링 기법 중에서, 가장 많이 사용하는 몇 가지 기법들을 중심으로 소개하겠다.

코드 가독성 높이는 Extract Method
첫 번째로 살펴볼 리팩토링 기법은 코드가 지나치게 길거나, 특정 코드가 반복해서 사용될 때 적용하는 Extract Method이다. 이 기법을 적용하는 이유는 간단하다. 우선 작은 크기로 쪼개진 메서드들은 재사용될 가능성이 높아지고 길게 늘어진 코드보다 이름이 명확한 여러 메서드를 호출하도록 코드를 작성하면 코드의 가독성이 높아지기 때문이다. 따라서 Extract Method를 수행할 때에는 코드를 잘게 쪼개는 목적뿐만 아니라 재사용성과 가독성도 고려해야 한다. 특히 추출한 메서드의 목적이 잘 드러나도록 이름을 지을 때 주의해야 한다.

Extract Method 기법을 적용하게 되는 가장 흔한 경우가 바로 데이터를 처리하는 부분과 출력하는 부분이 한 메서드에 동시에 있을 때이다. 일반적으로 다음과 같은 코드를 작성하기가 쉽다.

public static void ParseArgument(string argument){  string [] args = argument.Split(' ');   // args 처리 코드는 생략  // ….   // 입력된 인자들을 출력한다.  for ( int i = 0 ; i < args.Length; i++ )  {    Console.WriteLine ( "{0}: {1}", i, args[i] );  }}
소스 3 - Extract Method 기법을 적용할 예제 코드

이 코드에서 8번째 줄부터 12번째 줄까지의 코드는 입력된 인자를 화면에 보여주기 위한 코드로 인자를 분석하는 메서드에 포함될 필요가 없다. 대신 PrintArgument와 같은 이름의 메서드로 분리하는 것이 좋다. 자, 그럼 VSTS의 리팩토링 기능을 이용하여 이 코드를 PrintArgument 메서드로 분리해보자.

우선 Extract Method 기법을 적용할 코드 블록을 선택하고, 마우스 오른쪽 버튼을 클릭하여 <그림 1>과 같이 Refactor | Extract Method … 메뉴를 선택한다.

그림 1 - Extract Method 메뉴 선택

메 뉴를 선택하면 <그림 2>와 같이 새로 만들고자 하는 메서드의 이름을 입력할 수 있다. 한가지 알아두어야 할 사항은 <그림 2>의 밑 부분에 있는 것처럼 VSTS에서 자동으로 새로운 메서드에 전달될 매개 변수를 추가하고 있다는 점이다. 여기에서는 string[] args라는 매개 변수를 추가했는데, 원한다면 Preview method signature 텍스트 상자를 클릭하여 변경할 수도 있다.

그림 2 - Extract Method 대화 상자

메 서드 이름을 입력하고 OK 버튼을 클릭하면, 다음 <그림 3>과 같이 원래의 소스 코드에서 선택된 코드 블록은 PrintArgument라는 메서드로 작성되고 코드 블록이 있던 원래의 위치에는 PrintArgument 메서드를 호출하는 코드가 추가된다.

그림 3 - Extract Method가 적용된 후의 코드

쓸데 없는 매개 변수 지우개, Remove Parameters
코 드를 작성하다 보면 처음에는 사용했지만, 나중에는 사용하지 않게 되는 매개 변수들이 종종 있다. 원칙상으로는 그런 매개 변수들을 찾아서 제거해야 하겠지만, 프로그래머들이 사용되지 않는 매개 변수를 직접 찾아서 제거하는 경우는 찾아보기 어렵다. 물론 그렇게 하는 합당한 이유도 있지만, 대부분은 그 이유가 합당하지 않다. 가장 큰 이유는 지금은 사용하고 있지 않지만 언젠가 다시 사용해야 할지도 모르기 때문이며, 또는 다른 곳에서 메서드를 많이 호출하고 있어서 매개 변수를 제거하기가 꽤나 번거롭기 때문이다.

하지만 불필요한 매개 변수를 계속해서 사용하게 되면, 해당 메서드를 사용하는 개발자들이 계속해서 불필요한 매개 변수를 전달하는 수고를 해야 하고, 불필요한 매개 변수에 대한 목적이 불분명하게 되어 결국 혼란을 야기할 수도 있다. 이러한 문제는 프로그램을 유지 보수하는 시기에 특히 문제가 될 수 있다.

만약 <소스 3>에서 ParseParameter에 전달되는 argument 매개 변수를 클래스의 멤버 변수로 정의한다면, 더 이상 ParseParameter 메서드는 argument 매개 변수가 필요 없을 것이다(멤버 변수로 직접 접근이 가능하기 때문이다). 만약 argument 매개 변수를 제거하고 싶다면, Extract Method 기법에서와 마찬가지로 마우스 오른쪽 버튼을 클릭하여 Refactor | Remove Parameters 메뉴를 선택한다. ParseParameter 메서드는 argument를 매개 변수로 포함하고 있기 때문에, <그림 4>와 같이 매개 변수를 제거할 수 있다.

그림 4 - Remove Parameters 대화 상자

만 약 선택한 매개 변수를 제거해주기만 한다면, 굳이 VSTS의 리팩토링을 사용하지 않고, 소스 코드에서 직접 매개 변수를 제거하면 될 것이다. 당연히 VSTS는 원래의 메서드를 호출하고 있는 모든 코드를 찾아서 삭제된 매개 변수를 직접 제거해 준다(<그림 5> 참고). 이 때 매개 변수가 실제로 사용되고 있는지에 대한 여부는 검사하지 않기 때문에, 그 부분에 대해서는 개발자가 책임져야 한다. 만약 사용되고 있는 매개 변수를 제거했다면 당연히 컴파일 시에 오류가 발생할 것이다.

그림 5 - Remove Parameters가 적용된 코드

이름 변경도 깔끔하게, Rename
누 군가에게 "코드를 잘 정리하세요."라고 부탁한다면, 아마도 그는 제일 먼저 들여쓰기를 맞추고 변수나 메서드의 이름을 변경하는 작업부터 시작할 것이다. 0과 1만 인식하는 컴퓨터 입장에서 본다면 a나 b와 같은 변수를 사용해도 아무런 문제가 없겠지만, 사람은 a와 b 만으로는 이해할 수 없다. 그래서 temp나 temp1과 같이 임시로 사용했던 변수를 좀더 이해하기 쉬운 이름으로 변경해야 하는데, 단순히 찾아서 바꾸기의 기능을 이용하는 것만으로는 코드가 망가질 수 있으므로, 이럴 때에도 VSTS의 리팩토링 기능을 활용하자.

<소스 3>에서 for문에서 사용된 i를 index로 바꿔보기로 하자. 물론 예제 코드가 비교적 간단하기 때문에 i가 사용된 코드를 모두 찾아서 직접 바꾸어도 되겠지만, 리팩토링 기능을 이용하면 버튼 클릭 한번으로 모든 i를 index로 변경할 수 있다. 마찬가지로 코드 블록을 선택하고 마우스 오른쪽 버튼을 클릭하여 Refactor | Rename 메뉴를 선택한다. Rename 대화 상자에서 i 대신 index를 입력한 후 OK 버튼을 클릭하면 다음과 같이 index로 변경된 코드를 확인할 수 있다.

그림 6 - Preview Changes 대화 상자

리팩토링의 적극적인 활용이 필수
비 록 이 글의 서두에서 리팩토링에 대해서 간단히 소개하였지만, 리팩토링에 대해서 가장 잘 소개하고 있는 책은 Martin Fowler가 작성한 Refactoring: Improving the Design of Existing Code (Addison Wesley, 1999)이다. 이 글은 리팩토링 자체에 대한 소개가 아니라 VSTS에서 지원하는 리팩토링 기능에 대한 내용이기 때문에, 리팩토링 기능을 사용하기에 앞서 Refactoring을 읽고 올바른 리팩토링 적용 방법을 이해하도록 한다. 비록 VSTS가 Refactoring에서 소개하는 모든 리팩토링 기법을 지원하지는 않지만, 앞으로 여러 가지 다양한 리팩토링 기법이 추가될 가능성이 있으며, VSTS가 현재 제공하는 기능만으로도 점차적인 코드 개선이 충분히 가능하다고 본다. 특히 '복사해서 붙여 넣기' 신공을 자주 사용하는 개발자에게는 리팩토링이 매우 유용할 것이다.

필자 서우석님은 Microsoft MVP이며, 현재 카이스트 대학원 재학 중이며, C관련 프로그래밍에 능통하다.
[본문링크] 확장성 높은 코드의 재구성, 리팩토링 CSharp
[1]
코멘트(이글의 트랙백 주소:/cafe/tb_receive.php?no=3127
작성자
비밀번호

 

SSISOCommunity

[이전]

Copyright byCopyright ⓒ2005, SSISO Community All Rights Reserved.